import React, { useState, useEffect } from 'react';
import { Tree, message } from 'antd';
import type { ColumnsType } from 'antd/es/table';
import type { DataNode, TreeProps } from 'antd/es/tree';
import { connect, Dispatch } from 'umi';
import { PageContainer } from '@ant-design/pro-layout';
import ProCard from '@ant-design/pro-card';
import { TRADE_INIT, TRADE_LIST, TRADE_ADD, TRADE_UPDATE, IMPORT_TRADE, TRADE_UNMOUNT } from '@/actions/trade';
import { AButton, AGrid, AGridButtonCallBackModel } from '@/components/SelfComp';
import { ConnectState } from '@/models/connect';
import { AppItem } from '@/types/app';
import { DataItem, FlagEnum } from '@/types/global';
import { TradeItem } from '@/types/trade';
import { getItemValue } from '@/utils/commons';
import { AddTradeModal, ImportTradeModal, TradeQueryForm, UpdateTradeModal } from './components';

interface TradeListProps {
  dispatch: Dispatch;
  tradeList: TradeItem[],
  total: number,
  loading: boolean;
  pageSize: number;
  addLoading: boolean;
  updateLoading: boolean;
  systemData: DataItem[];
  clusterData: DataItem[];
  statusData: DataItem[];
  appList: AppItem[];
  importLoading: boolean;
}

type CheeckedKeysType = React.Key[] | {
  checked: React.Key[];
  halfChecked: React.Key[];
}

type TradeItemPartial = Partial<TradeItem>;

const EMPTY: TradeItem = {
  tradeId: '',
  funcCode: '',
  funcName: '',
  funcAction: '',
  systemCode: '',
  owner: '',
  clstCode: '',
  clstName: '',
  appCode: '',
  appName: '',
  status: '',
}

/**
 * 一颗空树
 */
const EMPTY_TREE: DataNode[] = [];

/**
 * 根据服务端返回的系统应用集合，系统集合，集群集合生成树形结构数据
 * @param appList 系统应用集合
 * @param systemData 系统集合
 * @param clusterData 集群集合
 * @returns 树形结构数据
 */
const createTreeData = (appList: AppItem[], systemData: DataItem[], clusterData: DataItem[]): DataNode[] => {
  if (!appList) {
    return EMPTY_TREE;
  }
  const len = appList.length;
  const treeData: DataNode[] = [];
  const keyExists: string[] = [];
  for (let i = 0; i < len; i += 1) {
    const appItem = appList[i];
    // console.info(appItem);
    const { systemCode, cluster, appCode, appName } = appItem;
    const treeNodeSize = treeData.length;
    // console.info('createTreeData', treeNodeSize);
    const keyStr: string = `${systemCode}-${cluster}`;
    const clusterName = getItemValue(clusterData, cluster);
    // 判断系统-集群是否存在
    if (keyExists.indexOf(keyStr) !== -1) {
      // 系统-集群存在
      for (let j = 0; j < treeNodeSize; j += 1) {
        const treeNode = treeData[j];
        const sysKey = treeNode['key'];
        // 找到对应系统节点
        if (sysKey === systemCode) {
          if (!treeNode.children) {
            treeNode.children = [];
          }
          const cluLen = treeNode.children.length;
          for (let k = 0; k < cluLen; k += 1) {
            const cluNode = treeNode.children[k];
            const cluKey = cluNode['key'];
            // 找到对应集群节点
            // 集群节点的key变成了系统编码-集群编码
            if (cluKey === keyStr) {
              // 集群存在
              const appNode = createNode(keyStr, appCode, appName, false);
              if (!cluNode.children) {
                cluNode.children = [];
              }
              cluNode.children.push(appNode);
            }
          }
        }
      }
    } else if (keyExists.indexOf(systemCode) !== -1) {
      // 系统存在，集群不存在
      for (let j = 0; j < treeNodeSize; j += 1) {
        const treeNode = treeData[j];
        const sysKey = treeNode['key'];
        // 找到对应系统节点
        if (sysKey === systemCode) {
          const appNode = createNode(keyStr, appCode, appName, false);
          const cluNode = createNode(systemCode, cluster, clusterName, true);
          cluNode.children!.push(appNode);
          if (!treeNode.children) {
            treeNode.children = [];
          }
          treeNode.children.push(cluNode);
        }
      }
    } else {
      // 系统不存在
      const systemNode = createTreeNode(appItem, systemData, clusterData);
      treeData.push(systemNode);
    }
    keyExists.push(systemCode);
    keyExists.push(keyStr);
  }
  return treeData;
}

/**
 * 创建节点
 * @param keyPre key前缀，可以不送
 * @param code code值
 * @param name 名称
 * @param hasSub 是否有子节点
 * @returns 节点
 */
const createNode = (keyPre: string, code: string, name: string, hasSub: boolean) => {
  let node: DataNode;
  if (keyPre) {
    node = {
      key: `${keyPre}-${code}`,
      title: `${code}-${name}`
    }
  } else {
    node = {
      key: `${code}`,
      title: `${code}-${name}`
    }
  }
  if (hasSub) {
    const subNode: DataNode[] = [];
    node.children = subNode;
  }
  return node;
}

/**
 * 将应用数据转换成树节点结构
 * @param treeData 树节点集合
 * @param appIiem 应用数据
 */
const createTreeNode = (appIiem: AppItem, systemData: DataItem[], clusterData: DataItem[]) => {
  // console.info('createTreeNode', systemData);
  const { systemCode, cluster } = appIiem;
  // 系统编码是否存在
  const systemName = getItemValue(systemData, systemCode);
  // 集群是否存在
  const clusterName = getItemValue(clusterData, cluster);
  // console.info('createTreeNode', systemName);
  const systemNode = createNode('', systemCode, systemName, true);
  const clusterNode = createNode(systemCode, cluster, clusterName, true);
  const { appCode, appName } = appIiem;
  const keyPre = `${systemCode}-${cluster}`;
  const appNode = createNode(keyPre, appCode, appName, false);
  clusterNode.children!.push(appNode);
  systemNode.children!.push(clusterNode);
  return systemNode;
}

const TradeList: React.FC<TradeListProps> = (props) => {
  // 新增弹窗
  const [addModalVisible, setAddModalVisible] = useState<boolean>(false);
  const [tradeFormData, setTradeFormData] = useState<TradeItem>(EMPTY);
  const [updateModalVisible, setUpdateModalVisible] = useState<boolean>(false);
  const [selectedRows, setSelectedRows] = useState<TradeItem[]>([]);
  const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
  // 查询表单
  const [queryParam, setQueryParam] = useState<TradeItemPartial>();
  // 默认为10
  const [pageSize, setPageSize] = useState<number>(10);
  const [flag, setFlag] = useState<FlagEnum>('edit');
  // 应用树相关属性
  // 单选某节点
  const [selectedKeys, setSelectedKeys] = useState<React.Key[]>([]);
  // 多选节点
  const [checkedKeys, setCheckedKeys] = useState<CheeckedKeysType>([]);
  const [autoExpandParent, setAutoExpandParent] = useState<boolean>(false);
  // 上传excel
  const [importModalVisible, setImportModalVisible] = useState<boolean>(false);

  useEffect(() => {
    console.info('TradeList.useEffect');
    // 查询本页面需所有参数
    const { dispatch } = props;
    dispatch(TRADE_INIT({}));
    return () => {
      dispatch(TRADE_UNMOUNT({}));
    }
  }, []);

  const columns: ColumnsType<TradeItem> = [
    {
      title: '交易功能码',
      dataIndex: 'funcCode',
      width: 120,
      ellipsis: true
    },
    {
      title: '交易名称',
      dataIndex: 'funcName',
      width: 150,
      ellipsis: true
    },
    {
      title: '交易路径',
      dataIndex: 'funcAction',
      width: 250,
      ellipsis: true
    },
    {
      title: '负责人',
      dataIndex: 'owner',
      width: 100,
    },
    {
      title: '交易所属系统',
      dataIndex: 'systemCode',
      width: 120,
    },
    {
      title: '交易所属集群',
      dataIndex: 'clstCode',
      width: 120,
    },
    {
      title: '交易所属应用',
      dataIndex: 'appCode',
      width: 120,
    }
  ]

  /**
   * 查询满足条件的数据字典
   */
  const handleSubmitEx = (record: TradeItem) => {
    // console.info('TradeList.handleSubmitEx');
    // console.info(record);
    const queryParam: TradeItemPartial = {
      ...record
    };
    if (selectedKeys.length > 0) {
      const selectedKey = selectedKeys[0] as string;
      const arr = selectedKey.split('-');
      // 数组解构
      const [systemCode, clstCode, appCode] = arr;
      queryParam.systemCode = systemCode;
      queryParam.clstCode = clstCode;
      queryParam.appCode = appCode;
    }
    // 查询条件保存起来，方便点击页码时使用
    // setState回调方法，保证先更新state
    setQueryParam(queryParam);
    fetchAllTrade(1, pageSize, queryParam);
  }

  const handleReset = () => {
    // 是否清空表格
  }

  const openAddTradeModal = () => {
    // console.info('openAddTradeModal');
    // console.info(records);
    if (selectedRowKeys.length === 1) {
      const row = selectedRows[0];
      setTradeFormData(row);
    }
    setAddModalVisible(true);
  }

  const handleAddModalOk = async (record: TradeItem) => {
    // console.log(record);
    const { dispatch } = props;
    const res = await dispatch(TRADE_ADD(record));
    // console.info(res);
    if (res) {
      setTradeFormData(EMPTY);
      setAddModalVisible(false);
      fetchAllTrade(1, pageSize, queryParam);
    }
  }

  const handleAddModalCancel = () => {
    setTradeFormData(EMPTY);
    setAddModalVisible(false);
  };

  const openUpdateTradeModal = (record: TradeItem[], flag: FlagEnum) => {
    // 表格选中内容
    // console.info('openUpdateTradeModal');
    // console.info(record);
    const row = record[0];
    const tradeFormData = {
      ...row,
    };
    setTradeFormData(tradeFormData);
    setFlag(flag);
    setUpdateModalVisible(true);
  }

  /**
   * 更新面板的确定事件
   * @param {*} record 更新表单
   */
  const handleUpdateModalOk = async (record: TradeItem) => {
    // console.log('handleUpdateModalOk');
    // console.log(record);
    // console.info(tradeFormData);
    if (flag === 'edit') {
      const { dispatch } = props;
      const res = await dispatch(TRADE_UPDATE(record));
      console.info(res);
      if (res) {
        setTradeFormData(EMPTY);
        setUpdateModalVisible(false);
        fetchAllTrade(1, pageSize, queryParam);
      }
    } else {
      setTradeFormData(EMPTY);
      setUpdateModalVisible(false);
    }
  }

  const handleUpdateModalCancel = () => {
    setTradeFormData(EMPTY);
    setUpdateModalVisible(false);
  };

  /**
   * 分页查询系统参数信息
   * @param {*} pageNum 页码
   * @param {*} pageSize 每页记录条数
   */
const fetchAllTrade = (pageNum: number, pageSize: number, queryParam?: TradeItemPartial) => {
    const { dispatch } = props;
    dispatch(TRADE_LIST({
      ...queryParam,
      pageSize,
      pageNum
    }));
  }

  /**
   * 处理按钮点击回调事件
   * @param {*} payload 数据包
   */
  const handleBtnCallBack = (callBackModel: AGridButtonCallBackModel<TradeItem>) => {
    // console.log('handleBtnCallBack');
    // console.log(callBackModel);
    // btn 按钮
    // keys 表格勾选数组
    const { code, keys } = callBackModel;
    // 新增
    if (code === 'add') {
      if (keys && keys.length > 1) {
        message.warn('新增时最多只允许选择一条数据当父节点！');
        return;
      }
      openAddTradeModal();
      return;
    }
    // 修改
    if (code === 'edit') {
      const { rows } = callBackModel;
      openUpdateTradeModal(rows, 'edit');
      return;
    }
    // 删除
    if (code === 'delete') {
      // const { rows } = callBackModel;
      // 调用删除服务，删除勾选数据
      return;
    }
    // 查看
    if (code === 'view') {
      const { rows } = callBackModel;
      openUpdateTradeModal(rows, 'view');
      return;
    }
  }

  /**
   * 表格勾选回调函数
   * @param {*} rows 表格选中数据集合
   */
  const onSelectRow = (keys: React.Key[], rows: TradeItem[]) => {
    setSelectedRowKeys(keys);
    setSelectedRows(rows);
  };

  /**
   * 页码改变的回调，参数是改变后的页码及每页条数
   * @param page 改变后的页码，上送服务器端
   * @param pageSize 每页数据条数
   */
  const onPageNumAndSizeChange = (page: number, pageSize: number) => {
    // console.log('onPageNumAndSizeChange', page, pageSize);
    setPageSize(pageSize);
    fetchAllTrade(page, pageSize, queryParam);
  };

  const onSelect: TreeProps['onSelect'] = (selectedKeys, _info) => {
    console.log('selected', selectedKeys);
    setSelectedKeys(selectedKeys);
    // 根据选择的节点，查询交易数据
    const selectedKey = selectedKeys[0] as string;
    const arr = selectedKey.split('-');
    // 数组解构
    const [systemCode, clstCode, appCode] = arr;
    const queryParamEx = {
      ...queryParam,
      systemCode,
      clstCode,
      appCode
    }
    // console.log('queryParamEx', queryParamEx);
    setQueryParam(queryParamEx);
    fetchAllTrade(1, pageSize, queryParamEx);
  };

  const onCheck: TreeProps['onCheck'] = (checkedKeys, info) => {
    // console.log('checked', checkedKeys, info);
    setCheckedKeys(checkedKeys);
  };

  const renderRightButton = () => {
    const { importLoading } = props;
    return (
      <>
        <AButton type='primary' code='import' pageCode='trade-list' name='批量导入' onClick={openImportTradeModal} loading={importLoading} />
      </>
    );
  }

  const openImportTradeModal = () => {
    setImportModalVisible(true);
  }

  const downloadTemplateFile = (fileName: string) => {
    console.info(fileName);
    message.success('模板下载成功');
  }

  /**
   * 批量导入弹窗确认事件
   * 
   * @param formData 表单数据
   */
  const handleImportModalOk = async (formData: FormData) => {
    console.log(formData.get('data'));
    const { dispatch } = props;
    const res = await dispatch(IMPORT_TRADE(formData));
    if (res) {
      message.success('导入成功');
      setImportModalVisible(false);
    }
  }

  const handleImportModalCancel = () => {
    setImportModalVisible(false);
  };

  const code = 'trade-list';
  const { tradeList, loading, total, addLoading, updateLoading, systemData, clusterData, appList, importLoading } = props;
  // 查询有哪些系统，系统下有哪些集群，集群下有哪些应用
  // 系统清单，集群清单，应用清单
  const treeData: DataNode[] = createTreeData(appList, systemData, clusterData);
  const rowKey = (record: TradeItem) => record.tradeId;

  return (
    <PageContainer>
      <ProCard split='vertical' >
        <ProCard title='项目系统应用' colSpan='17%' headerBordered>
          <Tree
            blockNode
            showLine
            autoExpandParent={autoExpandParent}
            onCheck={onCheck}
            checkedKeys={checkedKeys}
            onSelect={onSelect}
            selectedKeys={selectedKeys}
            treeData={treeData}
          />
        </ProCard>
        <ProCard title='交易列表' colSpan='83%' headerBordered>
          <TradeQueryForm
            colon={false}
            loading={loading}
            onSubmit={handleSubmitEx}
            onReset={handleReset}
          />
          <AGrid
            code={code}
            btnCallBack={handleBtnCallBack}
            renderRightButton={renderRightButton}
            columns={columns}
            rowKey={rowKey}
            pkField='tradeId'
            dataSource={tradeList}
            total={total}
            loading={loading}
            onSelectRow={onSelectRow}
            onPageNumAndSizeChange={onPageNumAndSizeChange}
            scroll={{x:1000}}
            actionColumnFixed={'right'}
          />
        </ProCard>
      </ProCard>
      {
        !addModalVisible ? null :
        <AddTradeModal
          appList={appList}
          systemData={systemData}
          clusterData={clusterData}
          colon={false}
          modalTitle='新增交易'
          modalWidth={1000}
          modalVisible={addModalVisible}
          loading={addLoading}
          onHandlerOK={handleAddModalOk}
          onHandlerCancel={handleAddModalCancel}
        />
      }
      {
        !updateModalVisible ? null :
        <UpdateTradeModal
          appList={appList}
          systemData={systemData}
          clusterData={clusterData}
          formData={tradeFormData}
          flag={'edit'}
          colon={false}
          modalTitle=''
          modalWidth={1000}
          modalVisible={updateModalVisible}
          loading={updateLoading}
          onHandlerOK={handleUpdateModalOk}
          onHandlerCancel={handleUpdateModalCancel}
        />
      }
      {
        importModalVisible  && (
          <ImportTradeModal
            appList={appList}
            systemData={systemData}
            clusterData={clusterData}
            colon={false}
            modalTitle='批量导入交易'
            modalWidth={1000}
            modalVisible={importModalVisible}
            loading={importLoading}
            onHandlerOK={handleImportModalOk}
            onHandlerCancel={handleImportModalCancel}
            downloadTemplateFile={downloadTemplateFile}
          />
        )
      }
    </PageContainer>
  );
}

export default connect(({ trades, loading }: ConnectState) => ({
  tradeList: trades.rows,
  total: trades.total,
  systemData: trades.systemData,
  clusterData: trades.clusterData,
  statusData: trades.statusData,
  appList: trades.appList,
  // 当用户 dispatch 对应 effect 时，dva 会自动注入对应 effect 的 loading 状态
  loading: loading.effects['trades/fetchAllTrade'],
  addLoading: loading.effects['trades/addTrade'],
  updateLoading: loading.effects['trades/updateTrade'],
  importLoading: loading.effects['trades/importTrade'],
}))(TradeList);